
Aloísio Vítor
Image Processing Expert
TL;DR: Usa Camoufox para evitar el fingerprinting del navegador y CapSolver para resolver automáticamente los CAPTCHAs como Cloudflare Turnstile y reCAPTCHA v2/v3. Juntos, permiten la automatización web estable y con comportamiento humano a escala con mínima detección y altas tasas de éxito.

La automatización web se ha vuelto esencial para la recopilación de datos, pruebas y diversas operaciones empresariales. Sin embargo, los sitios web modernos implementan medidas anti-bot y CAPTCHAs sofisticados que pueden detener incluso los scripts de automatización más cuidadosamente elaborados.
La combinación de Camoufox y CapSolver proporciona una solución poderosa para este desafío:
Juntos, estos herramientas permiten una automatización web fluida que evita tanto la detección de fingerprinting como los desafíos de CAPTCHA.
Este guía te ayudará a lograr tres objetivos principales:
Camoufox es una versión personalizada minimalista de Firefox diseñada específicamente para scraping y automatización web. A diferencia de otras soluciones anti-detección que dependen de la inyección de JavaScript (que puede ser detectada), Camoufox implementa el spoofing de fingerprinting a nivel de C++ dentro del navegador mismo.
# Instalar el paquete de Python
pip install -U camoufox[geoip]
# Descargar el navegador Camoufox
camoufox fetch
from camoufox.sync_api import Camoufox
with Camoufox(humanize=True) as browser:
page = browser.new_page()
page.goto("https://example.com")
CapSolver es un servicio de resolución automática de CAPTCHA impulsado por inteligencia artificial que soporta una amplia gama de tipos de CAPTCHA. Proporciona una API sencilla que te permite enviar desafíos de CAPTCHA y recibir soluciones en segundos.
Bonus: Use el código
CAMOUFOXal registrarse para recibir créditos adicionales!
Antes de combinar Camoufox con CapSolver, la automatización web enfrentaba varios problemas:
| Desafío | Impacto |
|---|---|
| Detección de fingerprinting de navegador | Los scripts se bloqueaban antes de llegar al contenido |
| Desafíos de CAPTCHA | Se requería resolución manual, interrumpiendo la automatización |
| Sistemas de reputación de IP | Los proxies se marcaban y prohibían rápidamente |
| Análisis de comportamiento | Patrones no humanos detectados |
La integración de Camoufox + CapSolver resuelve todos estos desafíos en un solo flujo de trabajo.
El enfoque de integración de API te da control total sobre el proceso de resolución de CAPTCHA y funciona con cualquier tipo de CAPTCHA.
pip install camoufox[geoip] httpx
import asyncio
import httpx
from camoufox.async_api import AsyncCamoufox
CAPSOLVER_API_KEY = "SU_CLAVE_DE_API"
CAPSOLVER_API = "https://api.capsolver.com"
async def create_task(task_payload: dict) -> str:
"""Crear una tarea de resolución de CAPTCHA y devolver el ID de la tarea."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{CAPSOLVER_API}/createTask",
json={
"clientKey": CAPSOLVER_API_KEY,
"task": task_payload
}
)
result = response.json()
if result.get("errorId") != 0:
raise Exception(f"Error de CapSolver: {result.get('errorDescription')}")
return result["taskId"]
async def get_task_result(task_id: str, max_attempts: int = 120) -> dict:
"""Esperar el resultado de la tarea hasta que se resuelva o se agote el tiempo."""
async with httpx.AsyncClient() as client:
for _ in range(max_attempts):
response = await client.post(
f"{CAPSOLVER_API}/getTaskResult",
json={
"clientKey": CAPSOLVER_API_KEY,
"taskId": task_id
}
)
result = response.json()
if result.get("status") == "ready":
return result["solution"]
elif result.get("status") == "failed":
raise Exception(f"Tarea fallida: {result.get('errorDescription')}")
await asyncio.sleep(1)
raise TimeoutError("La resolución de CAPTCHA expiró")
async def solve_captcha(task_payload: dict) -> dict:
"""Completar el flujo de resolución de CAPTCHA."""
task_id = await create_task(task_payload)
return await get_task_result(task_id)
También puedes usar la extensión de CapSolver con Camoufox para un enfoque más pasivo.
from camoufox.sync_api import Camoufox
with Camoufox(
addons=["/ruta/a/la-extensión-capsolver"],
headless=False # Las extensiones requieren modo con interfaz
) as browser:
page = browser.new_page()
# La extensión detectará y resolverá automáticamente los CAPTCHAs
Cloudflare Turnstile es uno de los desafíos de CAPTCHA más comunes. Así es como lo resuelves:
import asyncio
from camoufox.async_api import AsyncCamoufox
CAPSOLVER_API_KEY = "SU_CLAVE_DE_API"
CAPSOLVER_API = "https://api.capsolver.com"
async def solve_turnstile(site_key: str, page_url: str) -> str:
"""Resolver Cloudflare Turnstile y devolver el token."""
import httpx
async with httpx.AsyncClient() as client:
# Crear la tarea
response = await client.post(
f"{CAPSOLVER_API}/createTask",
json={
"clientKey": CAPSOLVER_API_KEY,
"task": {
"type": "AntiTurnstileTaskProxyLess",
"websiteURL": page_url,
"websiteKey": site_key,
}
}
)
task_id = response.json()["taskId"]
# Esperar el resultado
while True:
result = await client.post(
f"{CAPSOLVER_API}/getTaskResult",
json={
"clientKey": CAPSOLVER_API_KEY,
"taskId": task_id
}
)
data = result.json()
if data.get("status") == "ready":
return data["solution"]["token"]
await asyncio.sleep(1)
async def main():
target_url = "https://example.com/página-protegida"
turnstile_site_key = "0x4XXXXXXXXXXXXXXXXX" # Encuentre esto en el código fuente de la página
async with AsyncCamoufox(
humanize=True,
headless=False,
os="windows"
) as browser:
page = await browser.new_page()
await page.goto(target_url)
# Esperar a que se cargue Turnstile
await page.wait_for_selector('input[name="cf-turnstile-response"]', timeout=10000)
# Resolver el CAPTCHA
token = await solve_turnstile(turnstile_site_key, target_url)
print(f"Obtuve el token de Turnstile: {token[:50]}...")
# Inyectar el token
await page.evaluate(f'''
document.querySelector('input[name="cf-turnstile-response"]').value = "{token}";
// También establecer el callback oculto si está presente
const callback = document.querySelector('[data-callback]');
if (callback) {{
const callbackName = callback.getAttribute('data-callback');
if (window[callbackName]) {{
window[callbackName]('{token}');
}}
}}
''')
# Enviar el formulario
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
print("¡Turnstile evadido con éxito!")
if __name__ == "__main__":
asyncio.run(main())
import asyncio
from camoufox.async_api import AsyncCamoufox
CAPSOLVER_API_KEY = "SU_CLAVE_DE_API"
CAPSOLVER_API = "https://api.capsolver.com"
async def solve_recaptcha_v2(site_key: str, page_url: str) -> str:
"""Resolver reCAPTCHA v2 y devolver el token."""
import httpx
async with httpx.AsyncClient() as client:
# Crear la tarea
response = await client.post(
f"{CAPSOLVER_API}/createTask",
json={
"clientKey": CAPSOLVER_API_KEY,
"task": {
"type": "ReCaptchaV2TaskProxyLess",
"websiteURL": page_url,
"websiteKey": site_key,
}
}
)
result = response.json()
if result.get("errorId") != 0:
raise Exception(f"Error: {result.get('errorDescription')}")
task_id = result["taskId"]
# Esperar el resultado
while True:
result = await client.post(
f"{CAPSOLVER_API}/getTaskResult",
json={
"clientKey": CAPSOLVER_API_KEY,
"taskId": task_id
}
)
data = result.json()
if data.get("status") == "ready":
return data["solution"]["gRecaptchaResponse"]
elif data.get("status") == "failed":
raise Exception(f"Falló: {data.get('errorDescription')}")
await asyncio.sleep(2)
async def main():
target_url = "https://example.com/iniciar-sesión"
recaptcha_site_key = "6LcXXXXXXXXXXXXXXXXXXXXXXXXX" # Encuentre en el código fuente de la página
async with AsyncCamoufox(
humanize=True,
headless=False,
os=["windows", "macos"] # Selección aleatoria de sistema operativo
) as browser:
page = await browser.new_page()
await page.goto(target_url)
# Rellenar campos del formulario con pausas humanas
await page.fill('input[name="nombre_de_usuario"]', "usuario@ejemplo.com")
await asyncio.sleep(0.5) # Pausa similar a la humana
await page.fill('input[name="contraseña"]', "contraseña123")
# Resolver el CAPTCHA
print("Resolviendo reCAPTCHA v2...")
token = await solve_recaptcha_v2(recaptcha_site_key, target_url)
print(f"Obtuve el token: {token[:50]}...")
# Inyectar el token en el campo de respuesta de reCAPTCHA
await page.evaluate(f'''
document.getElementById('g-recaptcha-response').innerHTML = '{token}';
document.getElementById('g-recaptcha-response').style.display = 'block';
''')
# Enviar el formulario
await page.click('button[type="submit"]')
await page.wait_for_load_state("networkidle")
print("¡Inicio de sesión exitoso!")
if __name__ == "__main__":
asyncio.run(main())
reCAPTCHA v3 es basado en puntuación y no requiere interacción del usuario. Debe especificar el parámetro de acción.
import asyncio
from camoufox.async_api import AsyncCamoufox
CAPSOLVER_API_KEY = "SU_CLAVE_DE_API"
CAPSOLVER_API = "https://api.capsolver.com"
async def solve_recaptcha_v3(
site_key: str,
page_url: str,
action: str = "verify",
min_score: float = 0.7
) -> str:
"""Resolver reCAPTCHA v3 con acción y puntuación mínima especificados."""
import httpx
async with httpx.AsyncClient() as client:
response = await client.post(
f"{CAPSOLVER_API}/createTask",
json={
"clientKey": CAPSOLVER_API_KEY,
"task": {
"type": "ReCaptchaV3TaskProxyLess",
"websiteURL": page_url,
"websiteKey": site_key,
"pageAction": action,
"minScore": min_score
}
}
)
result = response.json()
if result.get("errorId") != 0:
raise Exception(f"Error: {result.get('errorDescription')}")
task_id = result["taskId"]
while True:
result = await client.post(
f"{CAPSOLVER_API}/getTaskResult",
json={
"clientKey": CAPSOLVER_API_KEY,
"taskId": task_id
}
)
data = result.json()
if data.get("status") == "ready":
return data["solution"]["gRecaptchaResponse"]
elif data.get("status") == "failed":
raise Exception(f"Falló: {data.get('errorDescription')}")
await asyncio.sleep(1)
async def main():
target_url = "https://example.com/buscar"
recaptcha_v3_key = "6LcXXXXXXXXXXXXXXXXXXXXXXXXX"
async with AsyncCamoufox(
humanize=2.0, # Máximo 2 segundos de movimientos humanizados
headless=True, # Puede ejecutarse en modo sin interfaz para v3
geoip=True, # Detectar geolocalización automáticamente desde el proxy
) as browser:
page = await browser.new_page()
await page.goto(target_url)
# Resolver reCAPTCHA v3 con acción "buscar"
print("Resolviendo reCAPTCHA v3...")
token = await solve_recaptcha_v3(
recaptcha_v3_key,
target_url,
action="buscar",
min_score=0.9 # Solicitar una alta puntuación
)
# Ejecutar la devolución de llamada con el token
await page.evaluate(f'''
// Enviar token a través de la devolución de llamada del sitio
grecaptcha.execute('{recaptcha_v3_key}', {action: 'search'})
.then(function(tokenOriginal) {
// Reemplazar con nuestro token resuelto
submitSearch('{token}');
});
''')
print("¡reCAPTCHA v3 evadido!")
if name == "main":
asyncio.run(main())
---
## Mejores prácticas
### 1. Rotación de proxies con GeoIP
Utiliza la función GeoIP de Camoufox para que las huellas dactilares coincidan automáticamente con la ubicación de tu proxy:
```python
async with AsyncCamoufox(
geoip=True, # Detectar automáticamente desde la IP del proxy
proxy={
"server": "http://proxy.example.com:8080",
"username": "user",
"password": "pass"
}
) as browser:
# La huella dactilar coincidirá con la ubicación geográfica del proxy
pass
Mantén las huellas dactilares consistentes dentro de una sesión pero rotalas entre sesiones:
from browserforge.fingerprints import Screen
# Limitar a tamaños de pantalla comunes
screen = Screen(
min_width=1280,
max_width=1920,
min_height=720,
max_height=1080
)
async with AsyncCamoufox(
os="windows",
screen=screen,
) as browser:
pass
Evita activar límites de velocidad añadiendo retrasos:
import random
async def retrasoHumano():
"""Retraso aleatorio para imitar el comportamiento humano."""
await asyncio.sleep(random.uniform(1.0, 3.0))
# Usar entre acciones
await page.click('button')
await retrasoHumano()
await page.fill('input', 'texto')
Siempre implementa un manejo adecuado de errores para la resolución de CAPTCHA:
async def resolverConReintento(payloadTarea: dict, maxReintentos: int = 3) -> dict:
"""Resolver CAPTCHA con lógica de reintento."""
for intento in range(maxReintentos):
try:
return await resolverCAPTCHA(payloadTarea)
except TimeoutError:
if intento < maxReintentos - 1:
print(f"Tiempo de espera agotado, reintentando... ({intento + 1}/{maxReintentos})")
await asyncio.sleep(5)
else:
raise
except Exception as e:
if "saldo" in str(e).lower():
raise # No reintentar errores de saldo
if intento < maxReintentos - 1:
await asyncio.sleep(2)
else:
raise
¿Listo para potenciar tu automatización web con Camoufox y CapSolver?
Usa el código CAMOUFOX al registrarte en CapSolver para recibir créditos adicionales!

Este bono exclusivo te ayudará a comenzar con la resolución de CAPTCHA de inmediato.
La integración de Camoufox y CapSolver crea una herramienta poderosa para la automatización web:
Ya sea que estés construyendo scrapers web, sistemas de pruebas automatizadas o pipelines de recolección de datos, esta combinación ofrece la fiabilidad y el sigilo que necesitas.
R: CapSolver admite todos los tipos principales de CAPTCHA. Cloudflare Turnstile y reCAPTCHA v2/v3 tienen las tasas de éxito más altas. La integración funciona sin problemas con cualquier CAPTCHA que CapSolver admita.
R: ¡Sí! Camoufox admite el modo headless y mantiene sus capacidades de suplantación de huellas dactilares. Para reCAPTCHA v3 y CAPTCHAs basados en tokens, el modo headless funciona perfectamente. Para CAPTCHAs visibles de v2, el modo con interfaz gráfica puede dar mejores resultados.
R: Búscalo en el código fuente de la página para:
data-sitekey o elementos cf-turnstiledata-sitekey en el div g-recaptchaR: Soluciones comunes:
R: Camoufox está basado en Playwright, no en Selenium. Sin embargo, puedes usar el mismo patrón de integración con cualquier framework de automatización de navegadores.
Aprende una arquitectura de raspado web escalable en Rust con reqwest, scraper, raspado asíncrono, raspado con navegador sin cabeza, rotación de proxies y manejo de CAPTCHA conforme.

Automatiza la resolución de CAPTCHA con Nanobot y CapSolver. Utiliza Playwright para resolver reCAPTCHA y Cloudflare autónomamente.
